package com.tonann.app.controller;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.tonann.app.VO.EnergyDashboardBuild;
import com.tonann.app.VO.EnergyDashboardFloor;
import com.tonann.app.VO.EnergyDashboardRoom;
import com.tonann.app.domain.*;
import com.tonann.app.dto.EnergyDataDto;
import com.tonann.app.excel.ElseData;
import com.tonann.app.excel.EnergyData;
import com.tonann.app.excel.EnergyRoom;
import com.tonann.app.excel.ReportBody;
import com.tonann.app.mapper.AppDevicePlacesMapper;
import com.tonann.app.mapper.AppSensorRecordDayMapper;
import com.tonann.app.mapper.AppSensorRecordMonthMapper;
import com.tonann.app.service.*;
import com.tonann.common.constant.CacheConstants;
import com.tonann.common.core.controller.BaseController;
import com.tonann.common.core.domain.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/app/energy/api")
public class AppEnergyDashboardApi extends BaseController {
    @Resource
    private IAppDeviceService appDeviceService;
    @Resource
    private IAppSensorService appSensorService;
    @Resource
    private IAppProjectService projectService;
    @Resource
    private IAppFaultService appFaultService;
    @Resource
    private AppDevicePlacesMapper devicePlacesMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private AppSensorRecordDayMapper recordDayMapper;
    @Resource
    private AppSensorRecordMonthMapper recordMonthMapper;

    @Resource
    private IAppSensorRecordService appSensorRecordService;

    @GetMapping("/main/{projectCode}")
    private AjaxResult getMainData(@PathVariable("projectCode") String projectCode) {
        AppProject project = projectService.selectAppProjectByProjectCode(projectCode);
        EnergyDashboardBuild build = new EnergyDashboardBuild();
        if (project != null) {
            AppDevice topDevice = new AppDevice();
            topDevice.setProjectId(project.getProjectId());
            topDevice.setParentId(0L);
            topDevice.setType("12");
            //根据设备结构树，先获取总体设备楼栋，再回去楼层，然后到房间。
            List<AppDevice> topDeviceList = appDeviceService.selectAppDeviceAll(topDevice);
            if (!topDeviceList.isEmpty()) {
                build.setDeviceId(topDeviceList.get(0).getDeviceId());
                build.setName(topDeviceList.get(0).getDeviceName());
                AppDevice secondDevice = new AppDevice();
                secondDevice.setProjectId(project.getProjectId());
                secondDevice.setParentId(topDeviceList.get(0).getDeviceId());
                secondDevice.setType("12");
                //获取楼层设备
                List<AppDevice> secondDeviceList = appDeviceService.selectAppDeviceAll(secondDevice);
                //楼层设备的字典
                Map<Long, EnergyDashboardFloor> deviceFloorMap = new HashMap<>();
                for (AppDevice device : secondDeviceList) {
                    List<AppDevicePlaces> placesList = devicePlacesMapper.selectAppDevicePlacesListByDeviceId(device.getDeviceId());
                    for (AppDevicePlaces places : placesList) {
                        if (places != null && places.getPlace() != null && places.getPlace().getParentId() != 0L) {
                            EnergyDashboardFloor floor = new EnergyDashboardFloor();
                            floor.setDeviceId(device.getDeviceId());
                            floor.setName(places.getPlace().getPlaceName());
                            deviceFloorMap.put(device.getDeviceId(), floor);
                        }
                    }
                }
                AppDevice bottomDevice = new AppDevice();
                bottomDevice.setProjectId(project.getProjectId());
                bottomDevice.setSubCount(0L);
                bottomDevice.setType("12");
                //获取最底层设备
                List<AppDevice> bottomDeviceList = appDeviceService.selectAppDeviceAll(bottomDevice);
                Map<Long, AppDevice> bottomDeviceMap = bottomDeviceList.stream().collect(Collectors.toMap(AppDevice::getDeviceId, Function.identity()));
                List<Long> bottomDeviceIds = bottomDeviceList.stream().map(AppDevice::getDeviceId).collect(Collectors.toList());
                //根据底层设备Id获取已经有传感器的底层设备的传感器
                List<AppSensor> bottomDeviceSensorList = appSensorService.selectAppSensorAllListByDeviceIds(bottomDeviceIds);
                //转换为有传感器的设备ID结合
                Set<Long> useBottomDeviceIdSet = bottomDeviceSensorList.stream().map(AppSensor::getDeviceId).collect(Collectors.toSet());
                build.setTotalSize(useBottomDeviceIdSet.size());
                //赛选出在线设备
                List<AppDevice> onlineDevice = bottomDeviceList.stream().filter(item ->
                        useBottomDeviceIdSet.contains(item.getDeviceId()) && item.getIsOnline() != null && item.getIsOnline().equals("1")
                ).collect(Collectors.toList());
                //筛选出告警设备
                List<AppDevice> exceptionDevice = bottomDeviceList.stream().filter(item ->
                        useBottomDeviceIdSet.contains(item.getDeviceId()) && item.getIsException() != null && item.getIsException().equals("1")
                ).collect(Collectors.toList());
                build.setOnlineSize(onlineDevice.size());
                build.setExceptionSize(exceptionDevice.size());
                BigDecimal onlineBig = new BigDecimal(onlineDevice.size());
                BigDecimal totalBig = new BigDecimal(useBottomDeviceIdSet.size());
                BigDecimal ratioBig = onlineBig.divide(totalBig, 4, RoundingMode.HALF_EVEN);
                ratioBig = ratioBig.multiply(new BigDecimal(100));
                if (ratioBig.compareTo(new BigDecimal(ratioBig.intValue())) == 0) {
                    build.setOnlineRate(new BigDecimal(ratioBig.intValue()));
                } else {
                    ratioBig = ratioBig.setScale(2, RoundingMode.HALF_EVEN);
                    build.setOnlineRate(ratioBig);
                }
                //上级设备与底层有传感器设备形成映射
                Map<Long, List<AppDevice>> bottomUpperDeviceIdMap = bottomDeviceList.stream().collect(Collectors.groupingBy(AppDevice::getParentId));
                //有传感器设备ID与设备下的传感器的映射
                Map<Long, List<AppSensor>> useDeviceSensorMap = bottomDeviceSensorList.stream().collect(Collectors.groupingBy(AppSensor::getDeviceId));
                for (Long parentId : bottomUpperDeviceIdMap.keySet()) {
                    EnergyDashboardFloor floor = deviceFloorMap.get(parentId);
                    if (floor != null) {
                        List<EnergyDashboardRoom> roomList = floor.getRoomList();
                        if (roomList == null) {
                            roomList = new ArrayList<>();
                        }
                        List<AppDevice> deviceList = bottomUpperDeviceIdMap.get(parentId);
                        BigDecimal lastDayEnergyTotal = BigDecimal.ZERO;
                        BigDecimal todayEnergyTotal = BigDecimal.ZERO;
                        if (deviceList != null) {
                            int floorTotalSize = deviceList.size();
                            int floorOnlineSize = 0;
                            int floorExceptionSize = 0;
                            for (AppDevice appDevice : deviceList) {
                                EnergyDashboardRoom room = new EnergyDashboardRoom();
                                room.setName(appDevice.getDeviceName());
                                room.setDeviceId(appDevice.getDeviceId());
                                if (appDevice.getIsOnline() != null && appDevice.getIsOnline().equals("1")) {
                                    floorOnlineSize++;
                                    room.setOnlineSize(1);
                                }
                                if (appDevice.getIsException() != null && appDevice.getIsException().equals("1")) {
                                    floorExceptionSize++;
                                    room.setExceptionSize(1);
                                }
                                List<AppSensor> sensorList = useDeviceSensorMap.get(appDevice.getDeviceId());
                                if (sensorList != null) {
                                    for (AppSensor sensor : sensorList) {
                                        BigDecimal value = getSensorValue(sensor);
                                        switch (sensor.getSensorType()) {
                                            case "6":
                                                if (sensor.getSensorName().contains("正向")) {
                                                    room.setPositiveEnergy(value);
                                                } else if (sensor.getSensorName().contains("反向")) {
                                                    room.setNegativeEnergy(value);
                                                }
                                                room.setEnergy(room.getEnergy().add(value));
                                                List<AppSensorRecordDay> recordDayList = recordDayMapper.selectAppSensorRecordDayListByInterval(sensor.getSensorId(), 1);
                                                recordDayList = recordDayList.stream().filter(record -> record.getValue() != null && new BigDecimal(record.getValue()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                                if (!recordDayList.isEmpty() && recordDayList.size() > 1) {
                                                    lastDayEnergyTotal = lastDayEnergyTotal.add(new BigDecimal(recordDayList.get(0).getValue()));
                                                    todayEnergyTotal = todayEnergyTotal.add(new BigDecimal(recordDayList.get(1).getValue()));
                                                }
                                                break;
                                            case "7":
                                                if (sensor.getSensorName().contains("有功")) {
                                                    room.setPositivePower(value);
                                                } else if (sensor.getSensorName().contains("无功")) {
                                                    room.setNegativePower(value);
                                                }
                                                room.setPower(room.getPower().add(value));
                                                break;
                                            case "11":
                                                if (sensor.getSensorName().contains("A相")) {
                                                    room.setPhaseACurr(value);
                                                } else if (sensor.getSensorName().contains("B相")) {
                                                    room.setPhaseBCurr(value);
                                                } else if (sensor.getSensorName().contains("C相")) {
                                                    room.setPhaseCCurr(value);
                                                }
                                                room.setCurr(room.getCurr().add(value));
                                                break;
                                            case "12":
                                                if (sensor.getSensorName().contains("A相")) {
                                                    room.setPhaseAVoltage(value);
                                                    if (value.compareTo(BigDecimal.ZERO) > 0) {
                                                        room.setExistPhaseA(room.getExistPhaseA() + 1);
                                                    }
                                                } else if (sensor.getSensorName().contains("B相")) {
                                                    room.setPhaseBVoltage(value);
                                                    if (value.compareTo(BigDecimal.ZERO) > 0) {
                                                        room.setExistPhaseB(room.getExistPhaseB() + 1);
                                                    }
                                                } else if (sensor.getSensorName().contains("C相")) {
                                                    room.setPhaseCVoltage(value);
                                                    if (value.compareTo(BigDecimal.ZERO) > 0) {
                                                        room.setExistPhaseC(room.getExistPhaseC() + 1);
                                                    }
                                                }
                                                room.setVoltage(room.getVoltage().add(value));
                                                break;
                                        }

                                    }
                                }
                                int existPhase = room.getExistPhaseA() + room.getExistPhaseB() + room.getExistPhaseC();
                                room.setVoltage(room.getVoltage()
                                        .divide(existPhase == 0 ? BigDecimal.ONE : BigDecimal.valueOf(existPhase)
                                                , 0, RoundingMode.HALF_EVEN));

                                roomList.add(room);
                            }
                            floor.setTotalSize(floorTotalSize);
                            floor.setOnlineSize(floorOnlineSize);
                            floor.setExceptionSize(floorExceptionSize);
                            if (lastDayEnergyTotal.compareTo(BigDecimal.ZERO) > 0 && todayEnergyTotal.compareTo(lastDayEnergyTotal) > 0) {
                                BigDecimal growthRate = todayEnergyTotal.subtract(lastDayEnergyTotal).divide(lastDayEnergyTotal, 4, RoundingMode.HALF_EVEN);
                                growthRate = growthRate.multiply(BigDecimal.valueOf(100));
                                if (growthRate.compareTo(BigDecimal.valueOf(growthRate.intValue())) == 0) {
                                    growthRate = BigDecimal.valueOf(growthRate.intValue());
                                    growthRate = growthRate.setScale(0, RoundingMode.HALF_EVEN);
                                } else {
                                    growthRate = growthRate.setScale(2, RoundingMode.HALF_EVEN);
                                }
                                floor.setGrowthRate(growthRate);
                            }
                        }

                        floor.setRoomList(roomList);
                        deviceFloorMap.put(parentId, floor);
                    }
                }
                Collection<EnergyDashboardFloor> floorCollection = deviceFloorMap.values();
                List<EnergyDashboardFloor> floorList = getFloorSortList(floorCollection);
                BigDecimal buildingEnergy = BigDecimal.ZERO;
                BigDecimal buildingPower = BigDecimal.ZERO;
                for (int i = 0; i < floorList.size(); i++) {
                    EnergyDashboardFloor floor = floorList.get(i);
                    List<EnergyDashboardRoom> roomList = floor.getRoomList();
                    if (roomList != null && !roomList.isEmpty()) {
                        BigDecimal energy = roomList.stream().map(EnergyDashboardRoom::getEnergy).reduce(BigDecimal::add).get();
                        BigDecimal power = roomList.stream().map(EnergyDashboardRoom::getPower).reduce(BigDecimal::add).get();
                        BigDecimal crr = roomList.stream().map(EnergyDashboardRoom::getCurr).reduce(BigDecimal::add).get();
                        BigDecimal crrA = roomList.stream().map(EnergyDashboardRoom::getPhaseACurr).reduce(BigDecimal::add).get();
                        BigDecimal crrB = roomList.stream().map(EnergyDashboardRoom::getPhaseBCurr).reduce(BigDecimal::add).get();
                        BigDecimal crrC = roomList.stream().map(EnergyDashboardRoom::getPhaseCCurr).reduce(BigDecimal::add).get();
                        BigDecimal volA = roomList.stream().map(EnergyDashboardRoom::getPhaseAVoltage).reduce(BigDecimal::add).get();
                        BigDecimal volB = roomList.stream().map(EnergyDashboardRoom::getPhaseBVoltage).reduce(BigDecimal::add).get();
                        BigDecimal volC = roomList.stream().map(EnergyDashboardRoom::getPhaseCVoltage).reduce(BigDecimal::add).get();
                        int existPhaseA = roomList.stream().map(EnergyDashboardRoom::getExistPhaseA).reduce(Integer::sum).get();
                        int existPhaseB = roomList.stream().map(EnergyDashboardRoom::getExistPhaseB).reduce(Integer::sum).get();
                        int existPhaseC = roomList.stream().map(EnergyDashboardRoom::getExistPhaseC).reduce(Integer::sum).get();
                        int existPhase = existPhaseA + existPhaseB + existPhaseC;
                        BigDecimal vol = volA.add(volB).add(volC);
                        vol = vol.divide(existPhase == 0 ? BigDecimal.ONE : BigDecimal.valueOf(existPhase), 0, RoundingMode.HALF_EVEN);
                        volA = volA.divide(existPhaseA == 0 ? BigDecimal.ONE : BigDecimal.valueOf(existPhaseA), 0, RoundingMode.HALF_EVEN);
                        volB = volB.divide(existPhaseB == 0 ? BigDecimal.ONE : BigDecimal.valueOf(existPhaseB), 0, RoundingMode.HALF_EVEN);
                        volC = volC.divide(existPhaseC == 0 ? BigDecimal.ONE : BigDecimal.valueOf(existPhaseC), 0, RoundingMode.HALF_EVEN);
                        floor.setEnergy(energy.setScale(2, RoundingMode.HALF_EVEN));
                        floor.setPower(power.divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_EVEN));
                        floor.setVoltage(vol.setScale(0, RoundingMode.HALF_EVEN));
                        floor.setPhaseAVoltage(volA.setScale(0, RoundingMode.HALF_EVEN));
                        floor.setPhaseBVoltage(volB.setScale(0, RoundingMode.HALF_EVEN));
                        floor.setPhaseCVoltage(volC.setScale(0, RoundingMode.HALF_EVEN));
                        floor.setCurr(crr.setScale(2, RoundingMode.HALF_EVEN));
                        floor.setPhaseACurr(crrA.setScale(2, RoundingMode.HALF_EVEN));
                        floor.setPhaseBCurr(crrB.setScale(2, RoundingMode.HALF_EVEN));
                        floor.setPhaseCCurr(crrC.setScale(2, RoundingMode.HALF_EVEN));
                    }
                    floorList.set(i, floor);
                    buildingEnergy = buildingEnergy.add(floor.getEnergy()).setScale(2, RoundingMode.HALF_EVEN);
                    buildingPower = buildingPower.add(floor.getPower()).setScale(2, RoundingMode.HALF_EVEN);
                }
                build.setFloorList(floorList);
                build.setPower(buildingPower);
                build.setEnergy(buildingEnergy);
            }
        }
        return AjaxResult.success(build);
    }

    @GetMapping("/alarm/{projectCode}")
    private AjaxResult getAlarmData(@PathVariable("projectCode") String projectCode) {
        AppProject project = projectService.selectAppProjectByProjectCode(projectCode);
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("totalSize", 0);
        resMap.put("checkSize", 0);
        resMap.put("uncheckSize", 0);
        List<AppFault> uncheckFaultList = new ArrayList<>();
        if (project != null) {
            AppDevice appDevice = new AppDevice();
            appDevice.setProjectId(project.getProjectId());
            List<AppDevice> appDeviceList = appDeviceService.selectAppDeviceAll(appDevice);
            if (!appDeviceList.isEmpty()) {
                List<AppFault> faultList = new ArrayList<>();
                Set<Long> appDeviceIds = appDeviceList.stream().map(AppDevice::getDeviceId).collect(Collectors.toSet());
                faultList = appFaultService.selectAppFaultByDeviceIds(appDeviceIds, null, null, null, null);
                uncheckFaultList = faultList.stream().filter(fault -> fault.getFaultHandle() == null || fault.getFaultHandle().getIsChecked() == null || fault.getFaultHandle().getIsChecked().equals("0")).collect(Collectors.toList());
                resMap.put("totalSize", faultList.size());
                resMap.put("uncheckSize", uncheckFaultList.size());
                resMap.put("checkSize", faultList.size() - uncheckFaultList.size());
            }
        }
        resMap.put("faultList", uncheckFaultList);
        return AjaxResult.success(resMap);
    }

    @GetMapping("/data/{projectCode}")
    private AjaxResult getStatisticalData(@PathVariable("projectCode") String projectCode) {
        AppProject project = projectService.selectAppProjectByProjectCode(projectCode);
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("r7d", 0);
        resMap.put("r30d", 0);
        resMap.put("lm", 0);
        if (project != null) {
            AppDevice appDevice = new AppDevice();
            appDevice.setProjectId(project.getProjectId());
            appDevice.setSubCount(0L);
            appDevice.setType("12");
            //获取最底层设备
            List<AppDevice> appDeviceList = appDeviceService.selectAppDeviceAll(appDevice);
//            Map<Long, AppDevice> appDeviceMap = appDeviceList.stream().collect(Collectors.toMap(AppDevice::getDeviceId, Function.identity()));
            List<Long> appDeviceIds = appDeviceList.stream().map(AppDevice::getDeviceId).collect(Collectors.toList());
            //根据底层设备Id获取已经有传感器的底层设备的传感器
            List<AppSensor> appDeviceSensorList = appSensorService.selectAppSensorAllListByDeviceIds(appDeviceIds);
            //转换为有传感器的电能表传感器
            List<AppSensor> energySensorList = appDeviceSensorList.stream().filter(item -> item.getSensorType().equals("6")).collect(Collectors.toList());
            List<Long> energySensorIdList = energySensorList.stream().map(AppSensor::getSensorId).collect(Collectors.toList());
            BigDecimal recentSevenDays = BigDecimal.ZERO;
            BigDecimal recent30Days = BigDecimal.ZERO;
            BigDecimal recentLastMonth = BigDecimal.ZERO;
            LinkedHashMap<String, BigDecimal> recentSevenDaysData = new LinkedHashMap<>();
            LinkedHashMap<String, BigDecimal> recent7DaysData = new LinkedHashMap<>();
            List<AppSensorRecordDay> record7DayAllList = recordDayMapper.selectAppSensorRecordDayListBySensorIdsAndInterval(energySensorIdList, 8);
            Map<LocalDate, List<AppSensorRecordDay>> record7DayMap = record7DayAllList.stream().collect(Collectors.groupingBy(AppSensorRecordDay::getCreateTime));
            for (LocalDate date : record7DayMap.keySet()) {
                List<AppSensorRecordDay> record7DayList = record7DayMap.get(date);
                BigDecimal total = record7DayList.stream().map(AppSensorRecordDay::getValue).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add);
                String dateStr = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                recent7DaysData.put(dateStr, total);
            }
            for (int i = 7; i > 0; i--) {
                LocalDate localDate = LocalDate.now();
                localDate = localDate.minusDays(i);
                String lastDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                BigDecimal lastDayRecord = recent7DaysData.get(lastDate);
                localDate = LocalDate.now();
                localDate = localDate.minusDays(i - 1);
                String todayDate = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                BigDecimal todayRecord = recent7DaysData.get(todayDate);
                if (todayRecord != null && lastDayRecord != null && todayRecord.compareTo(lastDayRecord) >= 0) {
                    todayRecord = todayRecord.subtract(lastDayRecord);
                } else {
                    todayRecord = BigDecimal.ZERO;
                }
                todayRecord = todayRecord.setScale(2, RoundingMode.HALF_EVEN);
                recentSevenDaysData.put(todayDate, todayRecord);
            }
            recentSevenDays = recentSevenDaysData.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            List<AppSensorRecordDay> record30DayAllList = recordDayMapper.selectAppSensorRecordDayListBySensorIdsAndInterval(energySensorIdList, 29);
            Map<Long, List<AppSensorRecordDay>> record30DayMap = record30DayAllList.stream().collect(Collectors.groupingBy(AppSensorRecordDay::getSensorId));
            for (Long sensorId : record30DayMap.keySet()) {
                List<AppSensorRecordDay> dayList = record30DayMap.get(sensorId);
                if (dayList != null) ;
                {
                    Optional<BigDecimal> max = dayList.stream().map(AppSensorRecordDay::getValue).map(BigDecimal::new).reduce(BigDecimal::max);
                    Optional<BigDecimal> min = dayList.stream().map(AppSensorRecordDay::getValue).map(BigDecimal::new).reduce(BigDecimal::min);
                    if (max.isPresent()) {
                        recent30Days = recent30Days.add(max.get().subtract(min.get()));
                    }
                }
            }
            List<AppSensorRecordMonth> recordMonthList = recordMonthMapper.selectAppSensorRecordMonthListBySensorIdsAndInterval(energySensorIdList, 2);
            Map<Long, List<AppSensorRecordMonth>> recordMonthMap = recordMonthList.stream().collect(Collectors.groupingBy(AppSensorRecordMonth::getSensorId));
            for (Long sensorId : recordMonthMap.keySet()) {
                List<AppSensorRecordMonth> monthList = recordMonthMap.get(sensorId);
                assert monthList != null;
                Optional<BigDecimal> max = monthList.stream().map(AppSensorRecordMonth::getValue).map(BigDecimal::new).reduce(BigDecimal::max);
                Optional<BigDecimal> min = monthList.stream().map(AppSensorRecordMonth::getValue).map(BigDecimal::new).reduce(BigDecimal::min);
                if (max.isPresent()) {
                    recentLastMonth = recentLastMonth.add(max.get().subtract(min.get()));
                }
            }
            resMap.put("r7d", recentSevenDays);
            resMap.put("r30d", recent30Days);
            resMap.put("lm", recentLastMonth);
            LinkedList<Map<String, Object>> linkedList = new LinkedList<>();
            for (String key : recentSevenDaysData.keySet()) {
                Map<String, Object> decimalMap = new HashMap<>();
                decimalMap.put("date", key);
                decimalMap.put("data", recentSevenDaysData.get(key));
                linkedList.add(decimalMap);
            }
            resMap.put("day", linkedList);
        }
        return AjaxResult.success(resMap);
    }

    private BigDecimal getSensorValue(AppSensor appSensor) {
        String value = null;
        Object object = redisTemplate.opsForValue().get(CacheConstants.APP_SENSOR_VALUE_KEY + appSensor.getDeviceId() + ":sensorId:" + appSensor.getSensorId());
        if (object != null) {
            if (object instanceof String) {
                value = object.toString();
            }
            if (object instanceof BigDecimal) {
                value = ((BigDecimal) object).toString();
            }
        }
        if (value != null) {
            BigDecimal bigDecimal = new BigDecimal(value);
            if (bigDecimal.compareTo(BigDecimal.ZERO) == 0) {
                AppSensorRecord appSensorRecord = appSensorRecordService.selectAppSensorRecordBySensorId(appSensor.getSensorId());
                if (appSensorRecord != null) {
                    return new BigDecimal(appSensorRecord.getValue());
                } else {
                    return BigDecimal.ZERO;
                }
            } else {
                return bigDecimal;
            }
        } else {
            AppSensorRecord appSensorRecord = appSensorRecordService.selectAppSensorRecordBySensorId(appSensor.getSensorId());
            if (appSensorRecord != null) {
                return new BigDecimal(appSensorRecord.getValue());
            } else {
                return BigDecimal.ZERO;
            }
        }
    }

    private List<EnergyDashboardFloor> getFloorSortList(Collection<EnergyDashboardFloor> collection) {

        // 输出排序结果
//        sortedItems.forEach(item -> System.out.println(item.getName()));
        return collection.stream()
                .sorted(Comparator.comparing(EnergyDashboardFloor::getName, (s1, s2) -> {
                            if (Character.isDigit(s1.charAt(0)) == Character.isDigit(s2.charAt(0))) {
                                return s1.compareTo(s2);
                            } else if (Character.isLetter(s1.charAt(0))) {
                                return -1;
                            } else {
                                return 1;
                            }
                        })
                        .thenComparingInt(item -> {
                            String name = item.getName();
                            if (Character.isDigit(name.charAt(0))) {
                                return Integer.parseInt(name.substring(0, 1));
                            }
                            return -1;
                        }))
                .collect(Collectors.toList());
    }

    Timer timer;
    TimerTask timerTask;

    private void intervalTask(int interval) {
        timer = new Timer();
        timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Interval task");
            }
        };
        timer.scheduleAtFixedRate(timerTask, 0, interval);
    }

    private void stopTimer() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    @GetMapping("/detail/rooms")
    public AjaxResult getRoomData(Long[] deviceIds, String startDateTime, String endDateTime, String dateType) {
        // 当前计算方式，多个deviceIds的就计算功率和电量相加，如果是单个设备的，需要获取相电压和相电流
        LinkedHashMap<String, BigDecimal> energyMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> powerMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> currAMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> currBMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> currCMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> volAMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> volBMap = new LinkedHashMap<>();
        LinkedHashMap<String, BigDecimal> volCMap = new LinkedHashMap<>();
        LocalDateTime startDate = LocalDateTime.parse(startDateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime endDate = LocalDateTime.parse(endDateTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        for (Long deviceId : deviceIds) {
            List<AppSensor> roomSensorList = appSensorService.selectAppSensorAllListByDeviceId(deviceId);
            for (AppSensor sensor : roomSensorList) {
                switch (sensor.getSensorType()) {
                    case "6": //电能
                        if (sensor.getSensorName().contains("正向")) {
                            getMapData(dateType, energyMap, startDate, endDate, sensor);
                        }
                        break;
                    case "7": //功率
                        if (sensor.getSensorName().contains("有功")) {
                            getMapData(dateType, powerMap, startDate, endDate, sensor);
                        }
                        break;
                    case "11": //电流
                        getMultipleMapDate(deviceIds, dateType, currAMap, currBMap, currCMap, startDate, endDate, sensor);
                        break;
                    case "12": //电压
                        getMultipleMapDate(deviceIds, dateType, volAMap, volBMap, volCMap, startDate, endDate, sensor);
                        break;
                }
            }
        }
        List<Map<String, EnergyDataDto>> resList = new ArrayList<>();
        resList.add(getEnergyDataDto(energyMap, "energy"));
        resList.add(getEnergyDataDto(powerMap, "power"));
        resList.add(getEnergyDataDto(currAMap, "currA"));
        resList.add(getEnergyDataDto(currBMap, "currB"));
        resList.add(getEnergyDataDto(currCMap, "currC"));
        resList.add(getEnergyDataDto(volAMap, "volA"));
        resList.add(getEnergyDataDto(volBMap, "volB"));
        resList.add(getEnergyDataDto(volCMap, "volC"));
        return AjaxResult.success(resList);
    }

    private void getMultipleMapDate(Long[] deviceIds, String dateType, LinkedHashMap<String, BigDecimal> aMap, LinkedHashMap<String, BigDecimal> bMap, LinkedHashMap<String, BigDecimal> cMap, LocalDateTime startDate, LocalDateTime endDate, AppSensor sensor) {
        if (deviceIds.length == 1) {
            if (sensor.getSensorName().contains("A相")) {
                if (dateType.equals("hours")) {
                    List<AppSensorRecord> hoursRecordList = getHoursRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (aMap.values().isEmpty()) {
                        for (AppSensorRecord it : hoursRecordList) {
                            aMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("days")) {
                    List<AppSensorRecordDay> dayRecordList = getDayRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (aMap.values().isEmpty()) {
                        for (AppSensorRecordDay it : dayRecordList) {
                            aMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("months")) {
                    List<AppSensorRecordMonth> monthRecordList = getMonthRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (aMap.values().isEmpty()) {
                        for (AppSensorRecordMonth it : monthRecordList) {
                            aMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM")), new BigDecimal(it.getValue()));
                        }
                    }
                }
            } else if (sensor.getSensorName().contains("B相")) {
                if (dateType.equals("hours")) {
                    List<AppSensorRecord> hoursRecordList = getHoursRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (bMap.values().isEmpty()) {
                        for (AppSensorRecord it : hoursRecordList) {
                            bMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("days")) {
                    List<AppSensorRecordDay> dayRecordList = getDayRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (bMap.values().isEmpty()) {
                        for (AppSensorRecordDay it : dayRecordList) {
                            bMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("months")) {
                    List<AppSensorRecordMonth> monthRecordList = getMonthRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (bMap.values().isEmpty()) {
                        for (AppSensorRecordMonth it : monthRecordList) {
                            bMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM")), new BigDecimal(it.getValue()));
                        }
                    }
                }
            } else if (sensor.getSensorName().contains("C相")) {
                if (dateType.equals("hours")) {
                    List<AppSensorRecord> hoursRecordList = getHoursRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (cMap.values().isEmpty()) {
                        for (AppSensorRecord it : hoursRecordList) {
                            cMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("days")) {
                    List<AppSensorRecordDay> dayRecordList = getDayRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (cMap.values().isEmpty()) {
                        for (AppSensorRecordDay it : dayRecordList) {
                            cMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), new BigDecimal(it.getValue()));
                        }
                    }
                } else if (dateType.equals("months")) {
                    List<AppSensorRecordMonth> monthRecordList = getMonthRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
                    if (cMap.values().isEmpty()) {
                        for (AppSensorRecordMonth it : monthRecordList) {
                            cMap.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM")), new BigDecimal(it.getValue()));
                        }
                    }
                }
            }
        }
    }

    private void getMapData(String dateType, LinkedHashMap<String, BigDecimal> map, LocalDateTime startDate, LocalDateTime endDate, AppSensor sensor) {
        if (dateType.equals("hours")) {
            List<AppSensorRecord> hoursRecordList = getHoursRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
            if (map.values().isEmpty()) {
                for (AppSensorRecord it : hoursRecordList) {
                    map.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), new BigDecimal(it.getValue()));
                }
            } else {
                int i = 0;
                for (String key : map.keySet()) {
                    BigDecimal value = map.get(key);
                    AppSensorRecord r = hoursRecordList.get(i);
                    value = value.add(new BigDecimal(r.getValue()));
                    map.put(key, value);
                    i++;
                }
            }
        } else if (dateType.equals("days")) {
            List<AppSensorRecordDay> dayRecordList = getDayRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
            if (map.values().isEmpty()) {
                for (AppSensorRecordDay it : dayRecordList) {
                    map.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), new BigDecimal(it.getValue()));
                }
            } else {
                int i = 0;
                for (String key : map.keySet()) {
                    BigDecimal value = map.get(key);
                    AppSensorRecordDay r = dayRecordList.get(i);
                    value = value.add(new BigDecimal(r.getValue()));
                    map.put(key, value);
                    i++;
                }
            }
        } else if (dateType.equals("months")) {
            List<AppSensorRecordMonth> monthRecordList = getMonthRecord(sensor.getSensorId(), startDate, endDate, sensor.getSensorType());
            if (map.values().isEmpty()) {
                for (AppSensorRecordMonth it : monthRecordList) {
                    map.put(it.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM")), new BigDecimal(it.getValue()));
                }
            } else {
                int i = 0;
                for (String key : map.keySet()) {
                    BigDecimal value = map.get(key);
                    AppSensorRecordMonth r = monthRecordList.get(i);
                    value = value.add(new BigDecimal(r.getValue()));
                    map.put(key, value);
                    i++;
                }
            }
        }
    }

    public Map<String, EnergyDataDto> getEnergyDataDto(LinkedHashMap<String, BigDecimal> map, String name) {
        EnergyDataDto dataDto = new EnergyDataDto();
        LinkedList<String> time = new LinkedList<>();
        LinkedList<BigDecimal> valueList = new LinkedList<>();
        for (String key : map.keySet()) {
            time.add(key);
            valueList.add(map.get(key));
        }
        dataDto.setName(name);
        dataDto.setTime(time);
        dataDto.setValue(valueList);
        Map<String, EnergyDataDto> valueMap = new HashMap<>();
        valueMap.put(name, dataDto);
        return valueMap;
    }

    public List<AppSensorRecord> getHoursRecord(Long sensorId, LocalDateTime startDate, LocalDateTime endDate, String sensorType) {
        AppSensorRecord sensorRecord = new AppSensorRecord();
        sensorRecord.setSensorId(sensorId);
        String begin = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        String end = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> params = new HashMap<>();
        params.put("beginTime", begin);
        params.put("endTime", end);
        sensorRecord.setParams(params);
        List<AppSensorRecord> recordList = appSensorRecordService.selectAppSensorRecordPureList(sensorRecord);
        LinkedList<AppSensorRecord> resList = new LinkedList<>();
        recordList = recordList.stream().collect(Collectors.collectingAndThen(Collectors.toMap(AppSensorRecord::getCreateTime, Function.identity(), (s1, s2) -> s1), map -> new ArrayList<>(map.values())));
        recordList = recordList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochSecond(ZoneOffset.of("+8")))).collect(Collectors.toList());
        if (sensorType.equals("6")) {
            AppSensorRecord record = appSensorRecordService.selectPreNoZeroAppSensorRecordByTime(recordList.get(0).getCreateTime(), sensorId);
            BigDecimal preValue = null;
            for (AppSensorRecord r : recordList) {
                BigDecimal big = new BigDecimal(r.getValue());
                BigDecimal resValue = BigDecimal.ZERO;
                if (big.compareTo(BigDecimal.ZERO) <= 0 && preValue == null) {
                    if (record != null) {
                        AppSensorRecord preRecord = appSensorRecordService.selectPreNoZeroAppSensorRecordByTime(r.getCreateTime(), sensorId);
                        if (preRecord != null) {
                            resValue = new BigDecimal(record.getValue()).subtract(new BigDecimal(preRecord.getValue()));
                        }
                    }
                    preValue = big;
                } else if (record != null && preValue == null) {
                    preValue = big;
                    resValue = big.subtract(new BigDecimal(record.getValue()));
                } else if (preValue != null) {
                    resValue = big.subtract(preValue);
                    preValue = new BigDecimal(r.getValue());
                }
                r.setValue(resValue.toString());
                resList.add(r);
            }
        }else {
            resList.addAll(recordList);
        }
        return resList;
    }

    public List<AppSensorRecordDay> getDayRecord(Long sensorId, LocalDateTime startDate, LocalDateTime endDate, String sensorType) {
        AppSensorRecordDay sensorRecord = new AppSensorRecordDay();
        sensorRecord.setSensorId(sensorId);
        String begin = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String end = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        Map<String, Object> params = new HashMap<>();
        params.put("beginDay", begin);
        params.put("endDay", end);
        sensorRecord.setParams(params);
        List<AppSensorRecordDay> recordList = recordDayMapper.selectAppSensorRecordDayList(sensorRecord);
        LinkedList<AppSensorRecordDay> resList = new LinkedList<>();
        recordList = recordList.stream().collect(Collectors.collectingAndThen(Collectors.toMap(AppSensorRecordDay::getCreateTime, Function.identity(), (s1, s2) -> s1), map -> new ArrayList<>(map.values())));
        recordList = recordList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochDay())).collect(Collectors.toList());
        if (sensorType.equals("6")) {
            AppSensorRecordDay record = recordDayMapper.selectPreNoZeroAppSensorRecordByTime(recordList.get(0).getCreateTime(), sensorId);
            BigDecimal preValue = null;
            for (AppSensorRecordDay r : recordList) {
                BigDecimal big = new BigDecimal(r.getValue());
                BigDecimal resValue = BigDecimal.ZERO;
                if (big.compareTo(BigDecimal.ZERO) <= 0 && preValue == null) {
                    if (record != null) {
                        AppSensorRecordDay preRecord = recordDayMapper.selectPreNoZeroAppSensorRecordByTime(record.getCreateTime(), sensorId);
                        if (preRecord != null) {
                            resValue = new BigDecimal(record.getValue()).subtract(new BigDecimal(preRecord.getValue()));
                        }
                    }
                    preValue = big;
                } else if (record != null && preValue == null) {
                    preValue = big;
                    resValue = big.subtract(new BigDecimal(record.getValue()));
                } else if (preValue != null) {
                    resValue = big.subtract(preValue);
                    preValue = new BigDecimal(r.getValue());
                }
                r.setValue(resValue.toString());
                resList.add(r);
            }
        }else {
            resList.addAll(recordList);
        }
        return resList;
    }

    public List<AppSensorRecordMonth> getMonthRecord(Long sensorId, LocalDateTime startDate, LocalDateTime endDate, String sensorType) {
        AppSensorRecordMonth sensorRecord = new AppSensorRecordMonth();
        sensorRecord.setSensorId(sensorId);
        String begin = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String end = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        Map<String, Object> params = new HashMap<>();
        params.put("beginMonth", begin);
        params.put("endMonth", end);
        sensorRecord.setParams(params);
        List<AppSensorRecordMonth> recordList = recordMonthMapper.selectAppSensorRecordMonthList(sensorRecord);
        LinkedList<AppSensorRecordMonth> resList = new LinkedList<>();
        recordList = recordList.stream().collect(Collectors.collectingAndThen(Collectors.toMap(AppSensorRecordMonth::getCreateTime, Function.identity(), (s1, s2) -> s1), map -> new ArrayList<>(map.values())));
        recordList = recordList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochDay())).collect(Collectors.toList());
        if (sensorType.equals("6")) {
            AppSensorRecordMonth record = recordMonthMapper.selectPreNoZeroAppSensorRecordByTime(recordList.get(0).getCreateTime(), sensorId);
            BigDecimal preValue = null;
            for (AppSensorRecordMonth r : recordList) {
                BigDecimal big = new BigDecimal(r.getValue());
                BigDecimal resValue = BigDecimal.ZERO;
                if (big.compareTo(BigDecimal.ZERO) <= 0 && preValue == null) {
                    if (record != null) {
                        AppSensorRecordMonth preRecord = recordMonthMapper.selectPreNoZeroAppSensorRecordByTime(recordList.get(0).getCreateTime(), sensorId);
                        if (preRecord != null) {
                            resValue = new BigDecimal(record.getValue()).subtract(new BigDecimal(preRecord.getValue()));
                        }
                    }
                    preValue = big;
                } else if (record != null && preValue == null) {
                    preValue = big;
                    resValue = big.subtract(new BigDecimal(record.getValue()));
                } else if (preValue != null) {
                    resValue = big.subtract(preValue);
                    preValue = new BigDecimal(r.getValue());
                }
                r.setValue(resValue.toString());
                resList.add(r);
            }
        }else {
            resList.addAll(recordList);
        }
        return resList;
    }

    ///报表
    @PostMapping(value = "/report")
    public void getReport(HttpServletResponse response, ReportBody body) throws Exception {
        // 设置响应头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("two_sheets_example", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        List<EnergyRoom> energyRoomList = new ArrayList<>();
        List<EnergyRoom> elseRoomList = new ArrayList<>();
        LocalDateTime startDateTime = LocalDateTime.parse(body.getStartDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime endDateTime = LocalDateTime.parse(body.getEndDateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        switch (body.getDateType()) {
            case "hours":
                break;
            case "days":
                endDateTime = endDateTime.withHour(23).withMinute(59).withSecond(59);
                break;
            case "months":
                endDateTime = endDateTime.withHour(23).withMinute(59).withSecond(59);
                endDateTime = endDateTime.plusMonths(1);
                endDateTime = endDateTime.minusDays(1);
                break;
        }
        if (body.getDeviceIds() != null && body.getDeviceIds().length > 0) {
            List<AppSensor> appSensorList = appSensorService.selectAppSensorAllListByDeviceIdsForAPP(Arrays.asList(body.getDeviceIds()));
            Map<Long, List<AppSensor>> deviceIdSensorMap = appSensorList.stream().collect(Collectors.groupingBy(AppSensor::getDeviceId));
            for (Long deviceId : body.getDeviceIds()) {
                AppDevice appDevice = appDeviceService.selectAppDeviceByDeviceId(deviceId);
                if (appDevice != null) {
                    EnergyRoom energyRoom = new EnergyRoom();
                    energyRoom.setRoomName(appDevice.getDeviceName());
                    List<AppSensor> sensorList = deviceIdSensorMap.get(deviceId);
                    Map<String, ElseData> dateTimeElseDataMap = new HashMap<>();
                    if (sensorList != null) {
                        for (AppSensor appSensor : sensorList) {
                            if (appSensor.getSensorName().contains("无功") || appSensor.getSensorName().contains("反向")) {
                                continue;
                            }
                            AppSensorRecord appSensorRecord = new AppSensorRecord();
                            Map<String, Object> params = new HashMap<>();
                            params.put("beginTime", startDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                            params.put("endTime",  endDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                            appSensorRecord.setParams(params);
                            appSensorRecord.setSensorId(appSensor.getSensorId());
                            List<AppSensorRecord> recordList = appSensorRecordService.selectAppSensorRecordPureList(appSensorRecord);
                            Map<String, List<AppSensorRecord>> dateTimeRecordMap = new HashMap<>();
                            switch (body.getDateType()) {
                                case "hours":
                                    dateTimeRecordMap = recordList.stream().collect(Collectors.groupingBy(item -> item.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时"))));
                                    break;
                                case "days":
                                    dateTimeRecordMap = recordList.stream().collect(Collectors.groupingBy(item -> item.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))));
                                    break;
                                case "months":
                                    dateTimeRecordMap = recordList.stream().collect(Collectors.groupingBy(item -> item.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy年MM月"))));
                                    break;
                            }
                            Set<String> dateTimeKeySet = dateTimeRecordMap.keySet();
                            dateTimeKeySet = dateTimeKeySet.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
                            List<EnergyData> energyDataList = new ArrayList<>();
                            for (String key : dateTimeKeySet) {
                                List<AppSensorRecord> valueList = dateTimeRecordMap.get(key);
                                valueList = valueList.stream().collect(Collectors.collectingAndThen(Collectors.toMap(AppSensorRecord::getCreateTime, Function.identity(), (s1, s2) -> s1), map -> new ArrayList<>(map.values())));
                                valueList = valueList.stream().sorted(Comparator.comparing(item -> item.getCreateTime().toEpochSecond(ZoneOffset.of("+8")))).collect(Collectors.toList());
                                if (appSensor.getSensorType().equals("6")) {
                                    EnergyData energyData = new EnergyData();
                                    energyData.setName(key);
                                    if (energyDataList.isEmpty()) {
                                        AppSensorRecord record = appSensorRecordService.selectPreNoZeroAppSensorRecordByTime(valueList.get(0).getCreateTime(), appSensor.getSensorId());
                                        if (record != null && record.getValue() != null) {
                                            energyData.setStartRecord(new BigDecimal(record.getValue()));
                                        } else {
                                            energyData.setStartRecord(new BigDecimal(valueList.get(0).getValue()));
                                        }
                                    } else {
                                        energyData.setStartRecord(energyDataList.get(energyDataList.size() - 1).getEndRecord());
                                    }
                                    energyData.setEndRecord(new BigDecimal(valueList.get(valueList.size() - 1).getValue()));
                                    energyData.setDiff(energyData.getEndRecord().subtract(energyData.getStartRecord()));
                                    energyDataList.add(energyData);
                                } else if (appSensor.getSensorType().equals("7")) {
                                    valueList = valueList.stream().filter(item -> item.getValue() != null && new BigDecimal(item.getValue()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                    Optional<BigDecimal> optBig = valueList.stream().map(AppSensorRecord::getValue).map(BigDecimal::new).reduce(BigDecimal::add);
                                    if (optBig.isPresent()) {
                                        BigDecimal average = optBig.get().divide(new BigDecimal(valueList.size()), 2, RoundingMode.HALF_EVEN);
                                        ElseData elseData = dateTimeElseDataMap.get(key);
                                        if (elseData == null) {
                                            elseData = new ElseData();
                                            elseData.setName(key);
                                        }
                                        elseData.setPower(average);
                                        dateTimeElseDataMap.put(key, elseData);
                                    }
                                } else if (appSensor.getSensorType().equals("11")) { //电流
                                    valueList = valueList.stream().filter(item -> item.getValue() != null && new BigDecimal(item.getValue()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                    Optional<BigDecimal> optBig = valueList.stream().map(AppSensorRecord::getValue).map(BigDecimal::new).reduce(BigDecimal::add);
                                    if (optBig.isPresent()) {
                                        BigDecimal average = optBig.get().divide(new BigDecimal(valueList.size()), 2, RoundingMode.HALF_EVEN);
                                        ElseData elseData = dateTimeElseDataMap.get(key);
                                        if (elseData == null) {
                                            elseData = new ElseData();
                                            elseData.setName(key);
                                        }
                                        if (appSensor.getSensorName().contains("A相")) {
                                            elseData.setCurrA(average);
                                        } else if (appSensor.getSensorName().contains("B相")) {
                                            elseData.setCurrB(average);
                                        } else if (appSensor.getSensorName().contains("C相")) {
                                            elseData.setCurrC(average);
                                        }
                                        dateTimeElseDataMap.put(key, elseData);
                                    }
                                } else if (appSensor.getSensorType().equals("12")) { //电流
                                    valueList = valueList.stream().filter(item -> item.getValue() != null && new BigDecimal(item.getValue()).compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                    Optional<BigDecimal> optBig = valueList.stream().map(AppSensorRecord::getValue).map(BigDecimal::new).reduce(BigDecimal::add);
                                    if (optBig.isPresent()) {
                                        BigDecimal average = optBig.get().divide(new BigDecimal(valueList.size()), 2, RoundingMode.HALF_EVEN);
                                        ElseData elseData = dateTimeElseDataMap.get(key);
                                        if (elseData == null) {
                                            elseData = new ElseData();
                                            elseData.setName(key);
                                        }
                                        if (appSensor.getSensorName().contains("A相")) {
                                            elseData.setVolA(average);
                                        } else if (appSensor.getSensorName().contains("B相")) {
                                            elseData.setVolB(average);
                                        } else if (appSensor.getSensorName().contains("C相")) {
                                            elseData.setVolC(average);
                                        }
                                        dateTimeElseDataMap.put(key, elseData);
                                    }
                                }
                            }
                            energyRoom.setDataList(energyDataList);
                        }
                    }
                    energyRoomList.add(energyRoom);
                    Set<String> keySet = dateTimeElseDataMap.keySet();
                    List<ElseData> elseDataList = new ArrayList<>();
                    keySet = keySet.stream().sorted().collect(Collectors.toCollection(LinkedHashSet::new));
                    for (String key : keySet) {
                        elseDataList.add(dateTimeElseDataMap.get(key));
                    }
                    energyRoom.setElseDataList(elseDataList);
                    elseRoomList.add(energyRoom);
                }
            }
        }
        List<List<Object>> data = new ArrayList<>();
        List<List<Object>> dataElse = new ArrayList<>();
        for (int i = 1; i <= energyRoomList.size(); i++) {
            List<Object> list = new ArrayList<>();
            list.add(i);
            EnergyRoom room = energyRoomList.get(i - 1);
            list.add(room.getRoomName());
            BigDecimal total = BigDecimal.ZERO;
            list.add(total);
            LocalDateTime _startDateTime = startDateTime;
            if (body.getDateType().equals("months")) {
                if (!room.getDataList().isEmpty()) {
                    long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                    EnergyData firstData = room.getDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonth = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月"));
                        if (firstData.getName().equals(yearMonth)) {
                            int j = 0;
                            for (; j < room.getDataList().size(); j++) {
                                EnergyData energyData = room.getDataList().get(j);
                                list.add(energyData.getStartRecord());
                                list.add(energyData.getEndRecord());
                                list.add(energyData.getDiff());
                                total = total.add(energyData.getDiff());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusMonths(1);
                    }
                } else {
                    long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            } else if (body.getDateType().equals("days")) {
                long monthsBetween = ChronoUnit.DAYS.between(_startDateTime, endDateTime);
                if (!room.getDataList().isEmpty()) {
                    EnergyData firstData = room.getDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonthDay = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
                        if (firstData.getName().equals(yearMonthDay)) {
                            int j = 0;
                            for (; j < room.getDataList().size(); j++) {
                                EnergyData energyData = room.getDataList().get(j);
                                list.add(energyData.getStartRecord());
                                list.add(energyData.getEndRecord());
                                list.add(energyData.getDiff());
                                total = total.add(energyData.getDiff());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusDays(1);
                    }
                } else {
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            } else if (body.getDateType().equals("hours")) {
                long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                if (!room.getDataList().isEmpty()) {
                    EnergyData firstData = room.getDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonthDayHours = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时"));
                        if (firstData.getName().equals(yearMonthDayHours)) {
                            int j = 0;
                            for (; j < room.getDataList().size(); j++) {
                                EnergyData energyData = room.getDataList().get(j);
                                list.add(energyData.getStartRecord());
                                list.add(energyData.getEndRecord());
                                list.add(energyData.getDiff());
                                total = total.add(energyData.getDiff());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusHours(1);
                    }
                } else {
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            }
            list.set(2, total);
            data.add(list);
        }
        for (int i = 1; i <= elseRoomList.size(); i++) {
            List<Object> list = new ArrayList<>();
            list.add(i);
            EnergyRoom room = elseRoomList.get(i - 1);
            list.add(room.getRoomName());
            LocalDateTime _startDateTime = startDateTime;
            if (body.getDateType().equals("months")) {
                long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                if (!room.getElseDataList().isEmpty()) {
                    ElseData firstData = room.getElseDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonth = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月"));
                        if (firstData.getName().equals(yearMonth)) {
                            int j = 0;
                            for (; j < room.getElseDataList().size(); j++) {
                                ElseData energyData = room.getElseDataList().get(j);
                                list.add(energyData.getCurrA());
                                list.add(energyData.getCurrB());
                                list.add(energyData.getCurrC());
                                list.add(energyData.getVolA());
                                list.add(energyData.getVolB());
                                list.add(energyData.getVolC());
                                list.add(energyData.getPower());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusMonths(1);
                    }
                } else {
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            } else if (body.getDateType().equals("days")) {
                long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                if (!room.getElseDataList().isEmpty()) {
                    ElseData firstData = room.getElseDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonthDay = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
                        if (firstData.getName().equals(yearMonthDay)) {
                            int j = 0;
                            for (; j < room.getElseDataList().size(); j++) {
                                ElseData energyData = room.getElseDataList().get(j);
                                list.add(energyData.getCurrA());
                                list.add(energyData.getCurrB());
                                list.add(energyData.getCurrC());
                                list.add(energyData.getVolA());
                                list.add(energyData.getVolB());
                                list.add(energyData.getVolC());
                                list.add(energyData.getPower());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusDays(1);
                    }
                } else {
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            } else if (body.getDateType().equals("hours")) {
                long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
                if (!room.getElseDataList().isEmpty()) {
                    ElseData firstData = room.getElseDataList().get(0);
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        String yearMonthDayHours = _startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时"));
                        if (firstData.getName().equals(yearMonthDayHours)) {
                            int j = 0;
                            for (; j < room.getElseDataList().size(); j++) {
                                ElseData energyData = room.getElseDataList().get(j);
                                list.add(energyData.getCurrA());
                                list.add(energyData.getCurrB());
                                list.add(energyData.getCurrC());
                                list.add(energyData.getVolA());
                                list.add(energyData.getVolB());
                                list.add(energyData.getVolC());
                                list.add(energyData.getPower());
                            }
                            break;
                        } else {
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                            list.add("");
                        }
                        _startDateTime = _startDateTime.plusHours(1);
                    }
                } else {
                    for (int k = 0; k < monthsBetween + 1; k++) {
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                        list.add("");
                    }
                }
            }
            dataElse.add(list);
        }
        List<List<String>> headList = new ArrayList<>();
        List<String> head0 = new ArrayList<>();
        head0.add(" ");
        head0.add("序号");
        headList.add(head0);
        List<String> head1 = new ArrayList<>();
        head1.add(" ");
        head1.add("房号");
        headList.add(head1);
        List<String> head2 = new ArrayList<>();
        head2.add(" ");
        head2.add("总用电量");
        headList.add(head2);
        LocalDateTime _startDateTime= startDateTime;
        if (body.getDateType().equals("months")) {
            long monthsBetween = ChronoUnit.MONTHS.between(_startDateTime, endDateTime);
            for (int i = 0; i < monthsBetween + 1; i++) {
                for (int j = 0; j < 3; j++) {
                    List<String> head = new ArrayList<>();
                    head.add(_startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月")));
                    head.add(j == 0 ? "月初值" : j == 1 ? "月末值" : "月用电量");
                    headList.add(head);
                }
                _startDateTime = _startDateTime.plusMonths(1);
            }
        } else if (body.getDateType().equals("days")) {
            long dayBetween = ChronoUnit.DAYS.between(_startDateTime, endDateTime);
            for (int i = 0; i < dayBetween + 1; i++) {
                for (int j = 0; j < 3; j++) {
                    List<String> head = new ArrayList<>();
                    head.add(_startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
                    head.add(j == 0 ? "日初值" : j == 1 ? "日末值" : "日用电量");
                    headList.add(head);
                }
                _startDateTime = _startDateTime.plusDays(1);
            }
        } else if (body.getDateType().equals("hours")) {
            long hoursBetween = ChronoUnit.HOURS.between(_startDateTime, endDateTime);
            for (int i = 0; i < hoursBetween + 1; i++) {
                for (int j = 0; j < 3; j++) {
                    List<String> head = new ArrayList<>();
                    head.add(_startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时")));
                    head.add(j == 0 ? "时初值" : j == 1 ? "时末值" : "时用电量");
                    headList.add(head);
                }
                _startDateTime = _startDateTime.plusHours(1);
            }
        }

        _startDateTime= startDateTime;
        List<List<String>> headElseList = new ArrayList<>();
        List<String> headElse0 = new ArrayList<>();
        headElse0.add(" ");
        headElse0.add("序号");
        headElseList.add(headElse0);
        List<String> headElse1 = new ArrayList<>();
        headElse1.add(" ");
        headElse1.add("房号");
        headElseList.add(headElse1);
        if (body.getDateType().equals("hours")) {
            long hoursBetween = ChronoUnit.HOURS.between(_startDateTime, endDateTime);
            for (int i = 0; i < hoursBetween + 1; i++) {
                for (int j = 0; j < 7; j++) {
                    List<String> head = new ArrayList<>();
                    head.add(_startDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时")));
                    switch (j) {
                        case 0:
                            head.add("A相电流");
                            break;
                        case 1:
                            head.add("B相电流");
                            break;
                        case 2:
                            head.add("C相电流");
                            break;
                        case 3:
                            head.add("A相电压");
                            break;
                        case 4:
                            head.add("B相电压");
                            break;
                        case 5:
                            head.add("C相电压");
                            break;
                        case 6:
                            head.add("功率");
                            break;
                    }
                    headElseList.add(head);
                }
                _startDateTime = _startDateTime.plusHours(1);
            }
        }
        try (OutputStream outputStream = response.getOutputStream()) {
            ExcelWriter excelWriter = EasyExcel.write(outputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(0, "用电量").registerWriteHandler(new HorizontalCellStyleStrategy(getHeadStyle(), getContentStyle())).head(headList).build();
            excelWriter.write(data, writeSheet);
            if (body.getDateType().equals("hours")) {
                WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "其他项目").registerWriteHandler(new HorizontalCellStyleStrategy(getHeadStyle(), getContentStyle())).head(headElseList).build();
                writeSheet1.setAutomaticMergeHead(true);
                writeSheet1.setUseDefaultStyle(false);
                excelWriter.write(dataElse, writeSheet1);
            }
            excelWriter.close();
        }
    }

    public static WriteCellStyle getHeadStyle() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景颜色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);

        // 字体
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontName("宋体");//设置字体名字
        headWriteFont.setFontHeightInPoints((short) 12);//设置字体大小
        headWriteFont.setBold(false);//字体加粗
        headWriteCellStyle.setWriteFont(headWriteFont); //在样式用应用设置的字体;
        // 样式
        headWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置底边框;
        headWriteCellStyle.setBottomBorderColor((short) 0);//设置底边框颜色;
        headWriteCellStyle.setBorderLeft(BorderStyle.THIN);  //设置左边框;
        headWriteCellStyle.setLeftBorderColor((short) 0);//设置左边框颜色;
        headWriteCellStyle.setBorderRight(BorderStyle.THIN);//设置右边框;
        headWriteCellStyle.setRightBorderColor((short) 0);//设置右边框颜色;
        headWriteCellStyle.setBorderTop(BorderStyle.THIN);//设置顶边框;
        headWriteCellStyle.setTopBorderColor((short) 0); //设置顶边框颜色;

        headWriteCellStyle.setWrapped(false);  //设置自动换行;

        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//设置水平对齐的样式为居中对齐;
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);  //设置垂直对齐的样式为居中对齐;
        headWriteCellStyle.setShrinkToFit(false);//设置文本收缩至合适

        return headWriteCellStyle;
    }


    /**
     * 内容样式
     *
     * @return WriteCellStyle
     */
    public static WriteCellStyle getContentStyle() {
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();

        // 背景颜色
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        //contentWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex());
        //contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);

        // 设置字体
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontHeightInPoints((short) 12);//设置字体大小
        contentWriteFont.setFontName("宋体"); //设置字体名字
        contentWriteCellStyle.setWriteFont(contentWriteFont);//在样式用应用设置的字体;

        //设置样式;
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置底边框;
        contentWriteCellStyle.setBottomBorderColor((short) 0);//设置底边框颜色;
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);  //设置左边框;
        contentWriteCellStyle.setLeftBorderColor((short) 0);//设置左边框颜色;
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);//设置右边框;
        contentWriteCellStyle.setRightBorderColor((short) 0);//设置右边框颜色;
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);//设置顶边框;
        contentWriteCellStyle.setTopBorderColor((short) 0); ///设置顶边框颜色;

        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 水平居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
        contentWriteCellStyle.setWrapped(true); //设置自动换行;
        contentWriteCellStyle.setShrinkToFit(true);//设置文本收缩至合适

        return contentWriteCellStyle;
    }
    public static LocalDateTime getLastDayOfMonth(LocalDateTime dateTime) {
        // 获取这个月的第一天
        LocalDateTime firstDayOfMonth = dateTime.withDayOfMonth(1);
        // 调整到下个月的第一天
        LocalDateTime firstDayOfNextMonth = firstDayOfMonth.plusMonths(1);
        // 减去一秒钟得到这个月的最后一刻
        LocalDateTime lastMomentOfMonth = firstDayOfNextMonth.minusSeconds(1);
        // 返回最后一刻的日期部分
        return lastMomentOfMonth.toLocalDate().atStartOfDay();
    }
}
